
<template>
  <div class="root">
    <!-- 工具栏 -->
    <Toolbar
      :default-config="toolbarConfig"
      :editor="editor"
      mode="simple"
      style="display: none"
    />
    <!-- 编辑器 -->
    <Editor
      :value="html"
      class="editor"
      :default-config="editorConfig"
      mode="simple"
      @onCreated="onCreated"
      @onChange="editorChange"
    />
  </div>
</template>

<script>
import { h } from 'snabbdom'
import { Boot, DomEditor } from '@wangeditor/editor'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import '@wangeditor/editor/dist/css/style.css'
import mentionModule from '@wangeditor/plugin-mention'
mentionModule.renderElems[0].renderElem = function(elem, children, editor) {
  // 当前节点是否选中
  const selected = DomEditor.isNodeSelected(editor, elem)
  const { value = '', info } = elem
  // 构建 vnode
  const vnode = h(
    'span',
    {
      props: {
        contentEditable: false // 不可编辑
      },
      // 自定义的属性 这个h的class没有效果 所以直接再attrs下编写
      attrs: {
        'data-id': info.id,
        class: 'w-mention'
      },
      style: {
        marginLeft: '3px',
        marginRight: '3px',
        backgroundColor: 'none',
        border: selected // 选中/不选中，样式不一样
          ? '2px solid #12DBFF' // wangEditor 提供了 css var https://www.wangeditor.com/v5/theme.html
          : '2px solid transparent',
        borderRadius: '3px',
        padding: '0 3px'
      },
      hook: {
        insert: (vNode) => {
          console.log(vNode, 9999)
          // console.log(SlateLocation, SlateRange, SlatePath, SlatePoint, 999999999)
          // console.log(editor.getNodePosition(elem)) // 恢复选区, 12)
        },
        destroy: (vNode) => {
          editor.emit('deleteMention', vNode)
        }
      }
    },
    `@${value}` // 如 `@张三`
  )

  return vnode
}
// 注册插件
Boot.registerModule(mentionModule)
export default {
  name: 'RichEditor',
  components: { Editor, Toolbar },
  props: {
    // eslint-disable-next-line vue/require-prop-type-constructor
    value: '',
    roles: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      editor: null,
      html: '',
      toolbarConfig: {
        toolbarKeys: []
      },
      editorConfig: {
        placeholder: '描述想要生成的镜头图片，可输入 @ 选择角色及形象素材',
        // autoFocus: false,
        // 所有的菜单配置，都要在 MENU_CONF 属性下
        MENU_CONF: {},
        EXTEND_CONF: {
          mentionConfig: {
            showModal: this.showMentionModal,
            hideModal: this.hideMentionModal
          }
        }
      },
      isShowModal: false,
      // 光标位置
      position: {
        top: '0px',
        left: '0px'
      }
    }
  },
  watch: {
    value: {
      handler(newVal) {
        this.html = newVal
      },
      immediate: true,
      deep: true
    }
  },
  beforeDestroy() {
    console.log('RichEditor beforeDestroy')
    const editor = this.editor
    if (editor == null) return
    editor.destroy() // 组件销毁时，及时销毁 editor ，重要！！！
  },
  methods: {
    onCreated(editor) {
      this.editor = Object.seal(editor) // 【注意】一定要用 Object.seal() 否则会报错
      this.editor.on('deleteMention', this.deleteMention)
    },
    showMentionModal() {
      this.$emit('showModal', true)
    },
    hideMentionModal() {
      this.$emit('showModal', false)
    },
    // 删除角色标签
    deleteMention(vNode) {
      // console.log(vNode, 8989)
    },
    // 插入角色标签
    insertMention(id, name) {
      const mentionNode = {
        type: 'mention', // 必须是 'mention'
        value: name,
        info: { id },
        children: [{ text: '' }] // 必须有一个空 text 作为 children
      }
      const editor = this.editor
      if (editor) {
        editor.restoreSelection() // 恢复选区
        console.log(editor.getText())
        editor.moveReverse(1) // 反向移动光标 没找到原因，不知道为啥需要向后移动一步光标，不然删除的位置不对
        editor.deleteForward('character') // 删除 '@'
        editor.insertNode(mentionNode) // 插入 mention
        editor.move(1) // 移动光标
      }
    },
    // 光标签插入文本
    insertText(text) {
      const editor = this.editor
      // 先判断提示词文本框是否存在改文本，如果存在弹窗提示，然后不插入
      const allText = this.getText()
      if (allText.includes(text)) {
        this.$baseMessage.error('该提示词标签已存在')
        return
      }
      if (editor) {
        editor.restoreSelection() // 恢复选区
        editor.insertText(`${text},`) // 插入文本
        // editor.move(1) // 移动光标
      }
    },
    // 编辑器内容发生变化时触发
    editorChange(editor) {
      this.$emit('update', editor.getHtml())
    },
    // // 自定义粘贴
    // customPaste(editor, event) {
    //   console.log(editor, event, 9999)
    //   const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
    //   console.log(text, 777)
    //   editor.insertText(text) // 插入文本
    //   // 阻止默认的粘贴行为
    //   event.preventDefault()
    //   return false
    // },
    getEditor() {
      return this.editor
    },
    getText() {
      const editor = this.editor
      if (editor == null) return
      return editor.getText()
    },
    getHtml() {
      const editor = this.editor
      if (editor == null) return
      return editor.getHtml()
    }
  }
}
</script>
<style lang="scss" scoped>
.root {
  position: relative;
}
.area {
  display: inline-block;
  vertical-align: top;
  max-width: 135px;
  text-align: justify;
  color: rgb(140, 140, 140);
}
.editor {
  display: inline-block;
  width: 100%;
  height: 120px;
  max-height: 120px;
  overflow-y: scroll;
  ::v-deep {
    .w-e-text-container {
      background: none !important;
      color: #FFFFFF !important;
    }
    .w-e-text-placeholder {
      top: 10px!important;
      font-style: normal;
    }
    .w-e-hover-bar {
      display: none!important;
    }
    .w-mention {
      background: none !important;
      color: $base-color-default !important;
    }
    p>span>span>span {
      background: none !important;
      color: #FFFFFF !important;
    }
  }
}
</style>

